package model.algorithms;

import java.util.List;

import model.config.Config;
import model.framework.Block;
import model.framework.BlockType;
import model.framework.Field;

public class BruteForceAlgorithm extends Algorithm {
	private int count = 0;
	private long l = 1;
	
	@Override
	public void run(List<Block> blocks, Field field) {
		
		for (Block b : blocks){
			l = (long) (l * b.getRotations() * 8.5);
		}
		Config.p("Brute force should have to do about " + l + " fields",2);
		Field finalField = testRestBlock(0,field, blocks);
		
		for (Block b : finalField.getBlockList()){
			field.placeBlock(b);
		}
		Config.p("Final field: \n" + finalField);
	}
	
	private Field testRestBlock(int index, Field testField, List<Block> blocks){
		count++;
		if (count % (l/4) == 0){
			Config.p("Did " + count + " fields",1);
		}
		Field bestField = null;
		if (index < blocks.size()){
			Block testBlock = blocks.get(index);
			int lowestHeight = -1;
			
			for (int rotation = 0; rotation < testBlock.getRotations(); rotation++){
				for (int x = 0; x < testField.getWidth() - testBlock.getBlockType().getWidth(rotation) + 1; x++) {
					Field newField = testField.clone();
					Block placeBlock = testBlock.clone();
					placeBlock.setX(x);
					placeBlock.setY(getYForX(x,testBlock.getBlockType(),rotation,newField));
					placeBlock.setRotation(rotation);
					newField.placeBlock(placeBlock);
					Field nextField = testRestBlock(index + 1, newField, blocks);
					if (lowestHeight == -1 || nextField.getTotalHeight() < lowestHeight ) {
						bestField = nextField;
						lowestHeight = nextField.getTotalHeight();
					}
				}
			}
		} else {
			bestField = testField;
			//Config.p(bestField);
		}
		return bestField;		
	}
	
	private int getYForX(int xOffset, BlockType testBlockType, int blockRotation, Field testField) {
		int highestY = -1;
		int[] blockSurface = testBlockType.getSurface(blockRotation);
		int[] fieldSurface = testField.getSurface();
		for (int x = 0; x < blockSurface.length; x++ ){
			int nextY = fieldSurface[xOffset+x] - blockSurface[x];
			if (highestY == -1 || nextY > highestY){
				highestY = nextY;
			}
		}
		return highestY;		
	}
	
	@Override
	public String toString() {
		return "BruteForce";
	}

}
